class MyPromise {
    constructor (executor){
        try {
            executor(this.resolve, this.reject);
        } catch (e) {
            this.reject(e);
        }
        
    }

    status = 'pending';//初始状态
    value = undefined; //成功后的返回值
    reason = undefined; //失败后的原因

    successCallback = []; //用于存储成功回调的队列
    failCallback = []; //用于存储失败回调的队列

    resolve = (value) => {
        if(this.status !== 'pending') return
        //resolve时状态如果不是pending则将状态改为fullfilled
        this.status = 'fullfilled';
        this.value = value;
        //调用成功回调里的函数直到队列为空
        while (this.successCallback.length){
            this.successCallback.shift()(this.value)
        }
    }

    reject = (reason) => {
        if(this.status !== 'pending') return
        this.status = 'rejected';
        this.reason = reason;

        //this.failCallback && this.failCallback (this.reason);
        while (this.failCallback) {
            this.failCallback.shift()(this.reason);
        }
    }

    then (successCallback, failCallback) {
        //判断是否存在成功回调， 如果不存在，则直接传递value（穿透）
        successCallback = successCallback ? successCallback: v=>v;
        failCallback = failCallback ? failCallback: v=>{ throw v};
        let promise2 = new MyPromise((resolve, reject)=>{
            if (this.status==='fullfilled') {
                //check if x is value or promise;
                setTimeout(()=>{
                    try {
                        let x = successCallback(this.value);
                        //resolvePromise is used to check
                        //1. whether the promise chain has cycle
                        //2. the x is value or promise 
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject (e);
                    }
                    
                }, 0)
                
            } else if (this.status === 'rejected') {
                setTimeout(() => {
                    try {
                      let x = failCallback(this.reason);
                      resolvePromise(promsie2, x, resolve, reject)
                    }catch (e) {
                      reject(e);
                    }
                  })
            } else {
                //if the status is pending
                //store the callback
                this.successCallback.push(() => {
                    setTimeout(() => {
                      try {
                        let x = successCallback(this.value);
                        resolvePromise(promsie2, x, resolve, reject)
                      }catch (e) {
                        reject(e);
                      }
                    })
                  });
                this.failCallback.push(() => {
                    setTimeout(() => {
                      try {
                        let x = failCallback(this.reason);
                        resolvePromise(promsie2, x, resolve, reject)
                      }catch (e) {
                        reject(e);
                      }
                    }, 0)
                  });
            }
        })
        return promise2;//return promise to make sure 'then' can be chained
    }
    
    static resolve (value) {
        if (value instanceof MyPromise) return value;
        return new MyPromise((resolve)=>resolve(value));
    }

    //当传入的所有promise对象都成功的时候才会触发成功，如果有一个失败 则立即触发失败
    static all (arr) {
        let result = [];
        return new MyPromise((resolve, reject)=>{
            for(let i=0; i<arr.length; i++){
                let current = arr[i];
                if(current instanceof MyPromise){
                    current.then(value => {result[i]=value}, (r)=>{reject(r)})
                } else {
                    result[i]=arr[i];
                }
            }
            if(result.length===arr.length)
                resolve(result);
        })
    }
    //当传入的promise对象有一个成功 则返回成功的promise的值
    static any (arr) {
        let count = 0;
        return new MyPromise((resolve,reject)=>{
            for(let i=0; i<arr.length; i++){
                let current = arr[i];
                if(current instanceof MyPromise){
                    current.then(value=>{
                        resolve(value);
                    }, ()=>{
                        count++;
                    })
                }else resolve(current)
            }
            //if all promises rejected, return error
            if (count===arr.length) reject(new AggregateError('All promises were rejected'));
        })
    }
    //if one of promises resolved or rejected, return resolve or reject;
    static race (arr) {
        return new MyPromise((resolve,reject)=>{
            for(let i=0; i<arr.length; i++){
                let current = arr[i];
                if(current instanceof MyPromise){
                    current.then(value => resolve(value), reason => reject(reason))
                }else resolve(current)
            }
        })
    }
    finally (callback){
        // finally will make sure the callbak will handle once
    // no matter the promise is resolved or rejected
        return this.then(v=>{
            //callback();
            return MyPromise.resolve(callback()).then(()=>value);   
        },r=>{
            //callback();
            return MyPromise.resolve(callback()).then(()=>{throw reason});
        })
    }
    catch(failCallback) {
        return this.then(undefined, failCallback)//keep the successcallback as undefined 
    }
}

function resolvePromise (promise2, x, resolve , reject) {
    //判断传入的promise对象是否为他本身
    if(promise2===x) {
        return reject(new TypeError('Chaining cycle detected for promise'))
    }
    if (x instanceof MyPromise) {
        x.then(resolve, reject);
    } else {
        resolve(x)
    }
}